package com.zhuanzhuan.hero.user.config;

import com.bj58.sfft.utility.tools.ThreadRenameFactory;
import com.bj58.zhuanzhuan.arch.threadpool.monitor.MonitorConfig;
import com.bj58.zhuanzhuan.arch.threadpool.monitor.MonitoredThreadPoolExecutor;
import com.zhuanzhuan.hero.biz.common.util.WxWarnTemplateUtil;
import com.zhuanzhuan.hero.user.consts.Consts;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.RejectedExecutionHandler;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * @ClassName ThreadPoolConfiguration
 * @Description 线程池配置
 * @Author hanjunjun
 * @Date 2023/11/10 16:16
 */
@Configuration
@Slf4j
public class ThreadPoolConfiguration {

    private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors();

    public static final String DEFAULT_EXECUTOR = "defaultExecutor";

    public static final String USER_RECENT_EXECUTOR = "userRecentExecutor";

    public static final String USER_BASE_INFO_EXECUTOR = "userBaseInfoExecutor";

    public static final String HOME_PAGE_INFO_EXECUTOR = "homePageInfoExecutor";

    public static final String BIZ_COUNT_EXECUTOR = "bizCountExecutor";

    public static final String USER_DETAIL_EXECUTOR = "defaultExecutor";

    /**
     * 可监控线程池
     *   全局通用的一个  线程数少队列大
     * @param
     * @return com.bj58.zhuanzhuan.arch.threadpool.monitor.MonitoredThreadPoolExecutor
     * @author  hanjunjun
     * @date 2024/7/3
     **/
    @Bean(DEFAULT_EXECUTOR)
    public MonitoredThreadPoolExecutor defaultExecutor() {
        log.info("本机CPU_COUNT={}", CPU_COUNT);
        MonitoredThreadPoolExecutor executor = new MonitoredThreadPoolExecutor(
            DEFAULT_EXECUTOR, 3 * CPU_COUNT, 5 * CPU_COUNT, 60, TimeUnit.SECONDS,
            new ArrayBlockingQueue<>(500),
            new ThreadRenameFactory("hero-user-default"), new CustomRejectedExecutionHandler(),
            new MonitorConfig().setQueueSlowTime(100)
                .setTaskSlowTime(100));
        log.info("线程池初始化完成, coreSize={},maxSize={},keepAliveTime={}s",
            executor.getCorePoolSize(), executor.getMaximumPoolSize(), executor.getKeepAliveTime(TimeUnit.SECONDS));

        return executor;
    }

    /**
     * 用户近期动态业务专用的线程池
     *   是IO密集型
     * @param
     * @return com.bj58.zhuanzhuan.arch.threadpool.monitor.MonitoredThreadPoolExecutor
     * @author  hanjunjun
     * @date 2024/7/27
     **/
    @Bean(USER_RECENT_EXECUTOR)
    public MonitoredThreadPoolExecutor userRecentExecutor() {
        MonitoredThreadPoolExecutor executor = new MonitoredThreadPoolExecutor(
            USER_RECENT_EXECUTOR, 100, 200, 60, TimeUnit.SECONDS,
            new ArrayBlockingQueue<>(50),
            new ThreadRenameFactory("hero-user-recent"), new CustomRejectedExecutionHandler(),
            new MonitorConfig()
                .setQueueSlowTime(50)
                .setTaskSlowTime(1000));
        log.info("线程池初始化完成, coreSize={},maxSize={},keepAliveTime={}s",
            executor.getCorePoolSize(), executor.getMaximumPoolSize(), executor.getKeepAliveTime(TimeUnit.SECONDS));

        return executor;
    }

    /**
     * 可监控线程池
     *   全局通用的一个  线程数少队列大
     * @param
     * @return com.bj58.zhuanzhuan.arch.threadpool.monitor.MonitoredThreadPoolExecutor
     * @author  hanjunjun
     * @date 2024/7/3
     **/
    @Bean(USER_BASE_INFO_EXECUTOR)
    public MonitoredThreadPoolExecutor userBaseInfoExecutor() {
        log.info("本机CPU_COUNT={}", CPU_COUNT);
        MonitoredThreadPoolExecutor executor = new MonitoredThreadPoolExecutor(
                USER_BASE_INFO_EXECUTOR, 5 * CPU_COUNT, 5 * CPU_COUNT, 60, TimeUnit.SECONDS,
                new ArrayBlockingQueue<>(500),
                new ThreadRenameFactory("user-base-executor"), new CustomRejectedExecutionHandler(),
                new MonitorConfig().setQueueSlowTime(100)
                        .setTaskSlowTime(100));
        log.info("用户基本信息组装线程池初始化完成, coreSize={},maxSize={},keepAliveTime={}s",
                executor.getCorePoolSize(), executor.getMaximumPoolSize(), executor.getKeepAliveTime(TimeUnit.SECONDS));

        return executor;
    }

    /**
     * 首页用户信息组装线程池
     * @param
     * @return com.bj58.zhuanzhuan.arch.threadpool.monitor.MonitoredThreadPoolExecutor
     * @author  hanjunjun
     * @date 2024/7/3
     **/
    @Bean(HOME_PAGE_INFO_EXECUTOR)
    public MonitoredThreadPoolExecutor homePageInfoExecutor() {
        log.info("本机CPU_COUNT={}", CPU_COUNT);
        MonitoredThreadPoolExecutor executor = new MonitoredThreadPoolExecutor(
                HOME_PAGE_INFO_EXECUTOR, 100, 200, 60, TimeUnit.SECONDS,
                new ArrayBlockingQueue<>(200),
                new ThreadRenameFactory("home-page-executor"), new CustomRejectedExecutionHandler(),
                new MonitorConfig().setQueueSlowTime(100)
                        .setTaskSlowTime(100));
        log.info("首页用户信息组装线程池初始化完成, coreSize={},maxSize={},keepAliveTime={}s",
                executor.getCorePoolSize(), executor.getMaximumPoolSize(), executor.getKeepAliveTime(TimeUnit.SECONDS));

        return executor;
    }

    /**
     * 计数专用线程池
     * @return
     */
    @Bean(BIZ_COUNT_EXECUTOR)
    public MonitoredThreadPoolExecutor bizCountExecutor() {
        log.info("本机CPU_COUNT={}", CPU_COUNT);
        MonitoredThreadPoolExecutor executor = new MonitoredThreadPoolExecutor(
                BIZ_COUNT_EXECUTOR, 5 * CPU_COUNT, 5 * CPU_COUNT, 60, TimeUnit.SECONDS,
                new ArrayBlockingQueue<>(200),
                new ThreadRenameFactory("biz-count-executor"), new CustomRejectedExecutionHandler(),
                new MonitorConfig().setQueueSlowTime(100)
                        .setTaskSlowTime(100));
        log.info("计数线程池初始化完成, coreSize={},maxSize={},keepAliveTime={}s",
                executor.getCorePoolSize(), executor.getMaximumPoolSize(), executor.getKeepAliveTime(TimeUnit.SECONDS));

        return executor;
    }

    /**
     * userDetail批量查询线程池
     * @return
     */
    @Bean(USER_DETAIL_EXECUTOR)
    public MonitoredThreadPoolExecutor userDetailExecutor() {
        log.info("本机CPU_COUNT={}", CPU_COUNT);
        MonitoredThreadPoolExecutor executor = new MonitoredThreadPoolExecutor(
                USER_DETAIL_EXECUTOR, 5 * CPU_COUNT, 5 * CPU_COUNT, 60, TimeUnit.SECONDS,
                new ArrayBlockingQueue<>(200),
                new ThreadRenameFactory("user-detail-default"), new CustomRejectedExecutionHandler(),
                new MonitorConfig().setQueueSlowTime(100)
                        .setTaskSlowTime(100));
        log.info("userDetail线程池初始化完成, coreSize={},maxSize={},keepAliveTime={}s",
                executor.getCorePoolSize(), executor.getMaximumPoolSize(), executor.getKeepAliveTime(TimeUnit.SECONDS));

        return executor;
    }



    /**
     * 线程池拒绝策略
     */
    private static class CustomRejectedExecutionHandler implements RejectedExecutionHandler {
        @Override
        public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
            log.info("线程池触发拒绝策略，及时优化  executorActiveCount={} Task={} rejected from={}",
                executor.getActiveCount(), r, executor);
            WxWarnTemplateUtil.warnOutService(Consts.SERVICE_NAME, "线程池触发拒绝策略，及时优化");
            //主线程执行
            r.run();
        }
    }

}
